home *** CD-ROM | disk | FTP | other *** search
- /* browse.c
- * This program allows you to view the contents of an ASCII
- * file. Once a file is displayed, you can scroll through the
- * file using the cursor pad keys (PgUp, PgDn, and so on). To
- * use the program, issue the following command at the DOS
- * prompt:
- * browse <filename>
- *
- * NOTE: COMPILE THIS IN LARGE MODEL ONLY
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <alloc.h>
- #include <dos.h>
- #include <dir.h>
- #include <conio.h>
- #include <sys\stat.h>
- #include <io.h>
-
- #define MaxBufSize 65520L /* Roughly 64K maximum file size */
- #define ScrSize 23 /* Number of text lines per screen */
- #define TabSize 5 /* Five spaces per tab */
- #define EscKey 27 /* Extended key codes */
- #define PgUp 73
- #define PgDn 81
- #define Home 71
- #define EndKey 79
- #define UpKey 72
- #define DnKey 80
- #define Alt_S 31 /* The search key */
- #define Screen (*ScreenPtr)
- #define TabKey 9
- #define CR 10 /* Carriage return */
-
- struct Texel { /* Record used for direct */
- char Ch; /* screen access */
- unsigned char Attr; /* Character attribute */
- };
-
- typedef struct Texel ScreenArea[25][80];
-
- FILE *InFile;
- ScreenArea far *ScreenPtr;
- long Time, Size;
- char *BufPtr, Ch;
- int LinePtr[2000]; /* Indexes of beginning lines in BufPtr */
- int Attr, NoBytes, I, Lc, Bot, End;
-
- char *GetStr(char *Str);
- /* CODE CHANGE: Must return a far pointer! */
- ScreenArea far *SelectMonitor(void);
- void DisplayFStat(char *fname, FILE *InFile, struct ffblk *ffblk);
- void DisplayCommands(void);
- void ShowScreen(void);
- void FileSearch(void);
- void ProcessInput(char Ch);
-
- int main(int argc, char *argv[])
- {
- struct ffblk ffblk;
- int DosError;
-
- clrscr();
- if (argc != 2) {
- printf("Incorrect number of arguments\n");
- printf("To browse a file use the command:\n");
- printf("\tbrowse <filename>\n");
- exit(1);
- }
- ScreenPtr = SelectMonitor();
- DosError = findfirst(argv[1], &ffblk, 0);
- if (DosError != 0) {
- printf("Can't find the file %s\n", argv[1]);
- exit(1);
- }
- if ((InFile=fopen(argv[1],"r")) == NULL) { /* Open file */
- printf("Cannot open file: %s\n", argv[1]);
- exit(1);
- }
- /* Allocate memory for the file buffer */
- if (ffblk.ff_fsize >= MaxBufSize) {
- printf("File too large: %s\n", argv[1]);
- exit(1);
- }
- if ((BufPtr=malloc(ffblk.ff_fsize)) == NULL) {
- printf("Not enough memory\n");
- exit(1);
- }
-
- DisplayFStat(argv[1], InFile, &ffblk);
- DisplayCommands();
- NoBytes = read(fileno(InFile), BufPtr, ffblk.ff_fsize);
- Lc = 0;
- LinePtr[Lc++] = 0; /* Initialize the line index array */
- for (I=0; I<NoBytes; I++)
- if (BufPtr[I] == CR)
- LinePtr[Lc++] = I + 1;
-
- fclose(InFile);
- if (Lc > ScrSize) /* Set the index that can display */
- Bot = Lc - ScrSize; /* the last screen full of the file */
- else Bot = 0;
- End = Lc - 1; /* Save line index to end of file */
- Lc = 0; /* Set the top line index */
- ShowScreen();
- do {
- Ch = getch();
- switch (Ch) {
- case 0: /* Extended key pressed */
- Ch = getch();
- ProcessInput(Ch); /* Perform operation */
- break;
- case EscKey: break; /* Do nothing for now */
- default: putch(7); /* Illegal key; sound the bell */
- }
- } while (Ch != EscKey);
- free(BufPtr);
- textbackground(0); /* Restore the screen */
- textcolor(7);
- clrscr();
- return 0;
- }
-
- char *GetStr(char *Str)
- /* Read a string at the current cursor location. Press Esc
- to abort read operation. */
- {
- char Ch;
- int Count = 0;
-
- while ((Ch=getch()) != 13 && Ch != EscKey) {
- printf("%c", Ch);
- Str[Count++] = Ch;
- }
- if (Ch == EscKey) return NULL;
- Str[Count] = '\0'; /* Terminate string */
- return Str;
- }
-
- /* CODE CHANGE: Must return a far pointer! */
- ScreenArea far *SelectMonitor(void)
- /* Determine the type of graphics card installed and return
- the memory address of the video memory */
- {
- union REGS Regs;
- unsigned Segment, Offset;
-
- Regs.h.ah = 15;
- int86(0x10, &Regs, &Regs);
- if (Regs.h.al == 7)
- Segment = 0xB000; /* Monochrome */
- else Segment = 0xB800; /* Graphics */
- Offset = Regs.h.bh * (unsigned)0x1000; /* Calculate video page */
- return (ScreenArea *)(((long)Segment << 16) | (long)Offset);
- }
-
- void DisplayFStat(char *fname, FILE *InFile, struct ffblk *ffblk)
- /* Display the first status line of file information */
- /* including file name, size, date, and time */
- /* CODE CHANGE: move for loop to last part of routine */
- {
- int Col;
- struct ftime ft;
- char AtStr[8];
-
- textbackground(7); /* Text is set to black on white */
- textcolor(0);
-
- gotoxy(3,1); /* Display filename */
- printf("File: %s",fname);
- gotoxy(26,1);
- getftime(fileno(InFile),&ft);
- printf("Date: %02u-%02u-%04u",ft.ft_month,
- ft.ft_day,ft.ft_year+1980);
- gotoxy(48,1); /* Display size */
- printf("Size: %ld",ffblk->ff_fsize);
-
- if (ffblk->ff_attrib == FA_RDONLY) /* Determine attributes */
- strcpy(AtStr,"R");
- else
- strcpy(AtStr,"R-W");
- if (ffblk->ff_attrib == FA_HIDDEN) strcat(AtStr,"-H");
- if (ffblk->ff_attrib == FA_SYSTEM) strcat(AtStr,"-S");
- gotoxy(63,1);
- printf("Attr: %s",AtStr); /* Display attributes */
- for (Col=0; Col<80; Col++) /* Put status bar in reverse video */
- Screen[0][Col].Attr = 112;
- }
-
- void DisplayCommands(void)
- /* Displays the command bar at the last line of the screen */
- /* CODE CHANGE: Change the printf() statement around with */
- /* the for loop */
- {
- int Col;
-
- gotoxy(2,25);
- printf("<Home=Top> <End=Bot> <PgUp=Prev> <PgDn=Next> "
- "<Alt-S=Search> <Esc=Quit>");
- for (Col=0; Col<80; Col++) Screen[24][Col].Attr = 112;
- }
-
- void ShowScreen(void)
- /* Display a screen image containing 23 lines of the file */
- {
- int Row, Col, TLc, I, Tp;
-
- TLc = Lc; /* Start with the current line index */
- for (Row=0; Row<ScrSize && Row<=End; Row++) {
- Tp = LinePtr[TLc];
- for (Col=0; Col<80 && Tp<NoBytes &&
- BufPtr[Tp] != CR; Tp++) {
- if (BufPtr[Tp] == TabKey) /* Look for tab key */
- for (I=0; I<TabSize && Col<80; I++)
- /* Replace tab with spaces */
- Screen[Row+1][Col++].Ch = ' ';
- else Screen[Row+1][Col++].Ch = BufPtr[Tp];
- }
- for (; Col<80; Col++) Screen[Row+1][Col].Ch = ' ';
- TLc++;
- }
- // Fill out the screen if the file has fewer than one
- // screen full of lines
- for (; Row<ScrSize; Row++)
- for (Col=0; Col<80; Col++)
- Screen[Row+1][Col].Ch = ' ';
- }
-
- void FileSearch(void)
- /* Search the file for a string starting from the current
- top line displayed. If a match is found, the line
- containing the string is highlighted. */
- {
- int Col, I, P;
- char *Ptr, SearchStr[81], *S, Line[81];
-
- for (Col=1; Col<=78; Col++) Screen[24][Col].Ch = ' ';
- gotoxy(2,25); printf("Search for: ");
- /* Get the search string */
- if ((S=GetStr(SearchStr)) == NULL) {
- DisplayCommands(); /* No string entered */
- return;
- }
- I = Lc;
- do {
- P = LinePtr[I];
- for (Col=0; Col<80 && BufPtr[P+Col] != CR; Col++)
- Line[Col] = BufPtr[P+Col];
- Line[Col] = '\0'; /* Terminate line string */
- Ptr = strstr(Line,S); /* Look for a match */
- I++;
- } while (Ptr == NULL && I <= End);
-
- if (Ptr != NULL) {
- if (I > Lc+ScrSize) {
- Lc = I - ScrSize;
- ShowScreen();
- }
- /* Highlight line with match */
- for (Col=0; Col<80; Col++) Screen[I-Lc][Col].Attr = 112;
- /* Wait until a key is pressed */
- if (getch() == 0) (void)getch();
- /* Set line of text back to normal */
- for (Col=0; Col<80; Col++) Screen[I-Lc][Col].Attr = 7;
- }
- DisplayCommands();
- }
-
- void ProcessInput(char Ch)
- /* Process the input keys */
- {
- switch (Ch) {
- case PgUp:
- if (Lc-ScrSize > 0) Lc -= ScrSize;
- else Lc = 0;
- ShowScreen();
- break;
- case PgDn:
- if (Lc+ScrSize < Bot && Bot >= ScrSize) Lc += ScrSize;
- else Lc = Bot;
- ShowScreen();
- break;
- case UpKey:
- if (Lc > 0) {
- Lc--;
- ShowScreen();
- }
- break;
- case DnKey:
- if (Lc < Bot && Bot >= ScrSize) {
- Lc++;
- ShowScreen();
- }
- break;
- case Home:
- Lc = 0;
- ShowScreen();
- break;
- case EndKey:
- if (Bot >= ScrSize) {
- Lc = Bot;
- ShowScreen();
- }
- break;
- case Alt_S: FileSearch(); break;
- }
- }
-
-